#include "socket.h"
#include "netinet/tcp.h"

// TCP服务端初始化
int socket_init()
{
    int s_fd;
    int ret;
    struct sockaddr_in s_addr;

    memset(&s_addr, 0, sizeof(struct sockaddr_in));

    // 1.socket
    s_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (s_fd == -1)
    {
        printf("socket error\n");
        exit(-1);
    }

    // int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
    s_addr.sin_family = AF_INET;          // Internet
    s_addr.sin_port = htons(SOCKET_PORT); // port
    // 把字符串形式地址转换成网络能识别的形式
    inet_aton(SOCKET_ADDRESS, &s_addr.sin_addr); // address

    // 2.bind
    bind(s_fd, (struct sockaddr *)&s_addr, sizeof(struct sockaddr_in));

    // 3.listen
    ret = listen(s_fd, 1);
    if (-1 == ret)
    {
        fprintf(stderr, "error listen\n");
        return -1;
    }

    return s_fd;
}

// 心跳包机制
int set_keepalive(int sockfd, int keepalive_idle, int keepalive_interval, int keepalive_count)
{
    int optval = 1;
    int optlen = sizeof(optval);

    // 启用keepalive
    if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &optval, optlen) < 0)
    {
        perror("setsockopt (SO_KEEPALIVE)");
        return -1;
    }

    // 在没有数据交换的keepalive_idle秒后开始发送探测包
    if (setsockopt(sockfd, SOL_TCP, TCP_KEEPIDLE, (void *)&keepalive_idle, sizeof(keepalive_idle)) < 0)
    {
        perror("setsockopt (TCP_KEEPIDLE)");
    }
    // 探测包之间的间隔
    if (setsockopt(sockfd, SOL_TCP, TCP_KEEPINTVL, (void *)&keepalive_interval, sizeof(keepalive_interval)) < 0)
    {
        perror("setsockopt (TCP_KEEPINTVL)");
    }
    // 探测次数，在探测失败多少次后关闭连接
    if (setsockopt(sockfd, SOL_TCP, TCP_KEEPCNT, (void *)&keepalive_count, sizeof(keepalive_count)) < 0)
    {
        perror("setsockopt (TCP_KEEPCNT)");
    }

    return 0;
}
